home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / examples / yafr_1.15 / YAFR.c < prev    next >
C/C++ Source or Header  |  1990-03-04  |  22KB  |  584 lines

  1. /*- - - - - - - - - - YAFR - Yet Another File Requester - - - - - - - - -*/
  2. /*- - - - - - - - - - - - - - Version  1.15 - - - - - - - - - - - - - - -*/
  3.  
  4. /*YAFR V1.15 Copyright (c)1989,1990 by Dave Schreiber. All rights reserved.*/
  5. /*YAFR is freely distributable, and may be sold as part of a commercial  */
  6. /*program. This copyright message must be included in the documentation  */
  7. /*for any program, commercial or otherwise, that uses YAFR. Use of YAFR  */
  8. /*in a rogram does not detract in any way from the ownership of YAFR by  */
  9. /*its author, Dave Schreiber, nor does it change its status as a freely  */
  10. /*distributable program.  Dave Schreiber reserves the right to forbid any*/
  11. /*person or company from incorporating YAFR as part of a program owned by*/
  12. /*that person or company.                                                */
  13.  
  14. /*Compiled under Lattice C V5.04                                         */
  15. /*Command line:  1> lc -cw -j30 yafr                                     */
  16. /*Generates YAFR.o which is linked into the host program                 */
  17.  
  18. /*If you have any comments, suggestions, etc. I can be reached at:       */
  19. /*Dave Schreiber                                                         */
  20. /*1234 Collins Lane                                                      */
  21. /*San Jose, CA   95129-4208                                              */
  22. /*Usenet:  davids@ucscb.ucsc.edu (during the school year)                */
  23. /*         davids@cup.portal.com (other times)                           */
  24.  
  25. #include "yafrHead.h"
  26.              /*^^^^system includes, structure definitions, etc.*/
  27. #define CRNT header.current->fib
  28.  
  29. /*Parameters are:  fn-string for filename (33 characters)                */
  30. /*dn-string for directory name (150 characters)                          */
  31. /*en-string for filename extension (.c, .pic, etc. 18 characters)        */
  32. /*cn-string for combined directory and filename (183 characters)         */
  33. /*(NULL if you don't want the combined filename)                         */
  34. /*X,Y-YAFR's window's X,Y location (relative to the screen               */
  35. /*wn-text for YAFR's window's title bar                                  */
  36. /*scr-Pointer to screen that window should appear on (NULL for           */
  37. /*Workbench) filepen-Pen color that filenames should be displayed in     */
  38. /*dirpen-Pen color that directory names should be displayed in           */
  39. /*DisableInfo-Boolean; TRUE-files ending in .info aren't displayed       */
  40. /*                     FALSE-.info files are displayed                   */
  41.  
  42. /*Note!  IntuitionBase, GfxBase, and DOSBase must be opened by the       */
  43. /*calling program before YAFR is called.  DOSBase is usually opened by   */
  44. /*the C startup code, but the other aren't.  If they aren't, YAFR will   */
  45. /*crash!  Be warned.                                                     */
  46.  
  47. /*Version 1.1, completed October 30, 1989*/
  48. /*Directory and filename string gadgets now auto-activate and appropriate*/
  49. /*times.  A bug that caused an incorrect filename to be returned when the*/
  50. /*user pressed CANCEL has been fixed                                     */
  51.  
  52. /*Version 1.15 completed January 23, 1990*/
  53. /*A bug that could cause the name of a directory to run outside the      */
  54. /*filename box has been eliminated.  Also, device names are now converted*/
  55. /*into volume names when selected from the device name buttons on the    */
  56. /*right (ex. on my system, when DH2: is pressed, Data: is the name that  */
  57. /*appears in the directory box.  The source code has had many more       */
  58. /*comments added to it and there are new distribution requirements.      */
  59.  
  60. /*Thanks to Bruce Rogers for his FindRoot program which has been         */
  61. /*incorporated in YAFR.                                                  */
  62.  
  63. /*-----------------------------------------------------------------------*/
  64.  
  65. /*Main function.  This is what is called by the host program:*/
  66. GetFilename(fn,dn,en,cn,X,Y,wn,scr,filepen,dirpen,DisableInfo)
  67. char *fn,*dn,*en,*cn,*wn;  /*See above for parameter definitions*/
  68. USHORT X,Y,filepen,dirpen;
  69. BYTE DisableInfo;
  70. struct Screen *scr;
  71. {
  72.    int status=GN_NEWDIR;
  73.    struct FileLock *DirLock;
  74.  
  75.    if(DisableInfo)
  76.       Info.Flags|=SELECTED;
  77.    else
  78.       Info.Flags=GADGHIMAGE|GADGIMAGE;
  79.  
  80.    yafr_e_FilenamePenColor = filepen;
  81.    yafr_e_DirnamePenColor = dirpen;
  82.    DirLock=(struct FileLock *)Lock(dn,ACCESS_READ);
  83.          /*Get lock on first directory*/
  84.                                  
  85.    strcpy(DirNameSIBuff,dn);  /*Copy some parameters to this modules*/
  86.    strcpy(ExtNameSIBuff,en);  /*variables*/
  87.    strcpy(filenameSIBuff,fn);
  88.    NewFNWindow.LeftEdge=X;
  89.    NewFNWindow.TopEdge=Y;
  90.    NewFNWindow.Title=(char *)wn;
  91.    NewFNWindow.Screen=(struct Screen *) scr;
  92.    
  93.          /*If there's a screen, open on it.  Workbench screen otherwise*/
  94.    NewFNWindow.Type= (scr) ? CUSTOMSCREEN : WBENCHSCREEN;
  95.  
  96.       /*Open the window*/
  97.    if((FNWindow=(struct Window *)OpenWindow(&NewFNWindow))==NULL)
  98.       {  /*If it failed...*/
  99.       UnLock(DirLock); /*Unlock the directory*/
  100.       return(FALSE);   /*and return*/
  101.       }
  102.       
  103.    /*Write some important text into the title bar:  */
  104.    SetWindowTitles(FNWindow,-1,"YAFR V1.15 (c)1989 by Dave Schreiber");
  105.    
  106.    SetAPen(FNWindow->RPort,1);
  107.    Move(FNWindow->RPort,6,19);
  108.    Text(FNWindow->RPort,"Directory",9);
  109.    Move(FNWindow->RPort,6,154);
  110.    Text(FNWindow->RPort,"Extension",9);
  111.    Move(FNWindow->RPort,6,165);
  112.    Text(FNWindow->RPort,"Filename",8);
  113.  
  114.       /*Activate the directory string gadget, for user's convenience*/
  115.         /*Note!  Window must be active for ActivateGadget to work on a*/
  116.         /*string window!  Take this into account in writing your own code.*/
  117.         /*I had to learn the hard way...:-( */
  118.    ActivateGadget(&DirName,FNWindow,NULL);
  119.    
  120.    /*Main loop:  While requests for reading a new directory keep coming in...*/
  121.    while((status = GetName(DirLock)) == GN_NEWDIR)
  122.       {                             /*keep doing it...*/
  123.       UnLock(DirLock);  /*Transfer lock to new directory*/
  124.       RefreshGadget(&DirName,FNWindow,NULL);
  125.       DirLock=(struct FileLock *)Lock(DirNameSIBuff,ACCESS_READ);
  126.       ActivateGadget(&filename,FNWindow,NULL); /*Activate filename gadget*/
  127.       }  /*Loop back, read the new directory, and wait for input again*/
  128.  
  129.    UnLock(DirLock); /*Or we could be finished*/
  130.    if(status) /*If OK pressed...*/
  131.    {
  132.       strcpy(fn,filenameSIBuff); /*Setup the return parameters*/
  133.       strcpy(dn,DirNameSIBuff);
  134.       strcpy(en,ExtNameSIBuff);
  135.       if(cn) /*If cn isn't NULL, there's space for a string, so...*/
  136.       {        /*construct the full filename for the host*/
  137.          strcpy(cn,DirNameSIBuff);
  138.          if( (dn[strlen(dn)-1] != ':') && strlen(dn) )
  139.             strcat(cn,"/");
  140.          strcat(cn,filenameSIBuff);
  141.       }
  142.    }
  143.  
  144.    CloseWindow(FNWindow); /*Close the window*/
  145.    return(status);      /*and return*/
  146. }
  147.  
  148. GetName(Lock)     /*Gets filenames in the directory associated with the*/
  149. struct FileLock *Lock;  /*lock, and also gets user input*/
  150. {
  151.    struct fibHeader header;
  152.    int status3,status2,status;
  153.    USHORT FNNumber=0;
  154.  
  155.    header.first=header.directory=NULL;
  156.    if(GetFib(&header)==FALSE)
  157.       return(FALSE);
  158.    SliderSInfo.VertPot=0;
  159.    UpdateSlider(1,&SliderSInfo,&Slider);
  160.    ClearFileBox();
  161.    if(!ispipedevice(DirNameSIBuff)) /*Check for pipe: device*/
  162.       if(Lock!=NULL) /*If the lock (& the directory) exist...*/
  163.          {
  164.          Examine(Lock,&(CRNT));  /*Get the first entry*/
  165.          if(GetFib(&header)==FALSE)  /*Get next node*/
  166.             return(NULL);
  167.          while((status3=ExNext(Lock,&(CRNT)))) /*Loop while there are files*/
  168.             {
  169.             if((status2=((CheckExt(CRNT.fib_FileName,ExtNameSIBuff) ||
  170.                   CRNT.fib_DirEntryType > 0) && /*If the specified extension*/
  171.                   CheckInfo(CRNT.fib_FileName)) )) /*(if any) matches and*/
  172.                {              /*it isn't a .info file (if masked)*/
  173.                if(FNNumber<10)   /*display it...*/
  174.                   PrintFileName(&(CRNT),Rp,XBorder,YBorder+(10*FNNumber++));
  175.                else  /*or update the slider (if the filename box is full)*/
  176.                   UpdateSlider(++FNNumber,&SliderSInfo,&Slider);
  177.                }
  178.             while((status=CheckIntuiMessages(FNNumber,&header))!=GN_DONE)
  179.                {  /*After getting a name, checked for IDCMP messages*/
  180.                if(status==GN_PARENT) /*If PARENT was pressed*/
  181.                   {
  182.                   Parentize(DirNameSIBuff); /*Setup the parent dir*/
  183.                   RefreshGadget(&DirName,FNWindow,NULL);
  184.                   FreeFuncMemory(header.directory); /*Free the filename*/
  185.                   return(GN_NEWDIR);   /*list and return*/
  186.                   }
  187.                if(status < GN_PARENT)
  188.                   {
  189.                   FreeFuncMemory(header.directory);
  190.                   return(status);   /*For OK,NEWDIR, & CANCEL*/
  191.                   }
  192.                }
  193.             if(status2) /*If the filename was valid, append another Fib*/
  194.                if(GetFib(&header)==FALSE) /*structure for the next filename*/
  195.                   return(NULL);
  196.               /*If not valid, let the next filename info overwrite the current*/
  197.               /*Fib*/
  198.             }
  199.             header.current->prev->next=NULL; /*Delete the last (unused) Fib*/
  200.             if(header.directory->next == header.current) /*If no files*/
  201.                header.directory->next=header.first=header.last=
  202.                      header.top=NULL;     /*NULL certain pointers*/
  203.             FreeMem(header.current,sizeof(struct fibNode));
  204.          }
  205.    for(;;)  /*Loop until the users says 'Change something!'*/
  206.       {
  207.       Wait(1<<FNWindow->UserPort->mp_SigBit);
  208.       while((status=CheckIntuiMessages(FNNumber,&header))!=GN_DONE)
  209.          {
  210.          if(status==GN_PARENT)   /*PARENT pushed*/
  211.             if(Parentize(DirNameSIBuff))
  212.                {
  213.                RefreshGadget(&DirName,FNWindow,NULL);
  214.                FreeFuncMemory(header.directory);
  215.                return(GN_NEWDIR);
  216.                }
  217.          if(status < GN_PARENT)  /*Something else pushed*/
  218.             {
  219.             FreeFuncMemory(header.directory);
  220.             return(status);   /*For OK,NEWDIR, & CANCEL*/
  221.             }
  222.          }
  223.       }
  224. }
  225.  
  226. CheckInfo(name)  /*Check to see if .info's should be printed*/
  227. char *name;
  228. {
  229.    if(!(Info.Flags & SELECTED))
  230.       return(TRUE);
  231.  
  232.    return(!(strcmp(&name[strlen(name)-5],".info")==0));
  233. }
  234.  
  235. ClearFileBox() /*Clear the box with the filenames in it*/
  236. {
  237.    SetAPen(Rp,0);
  238.    RectFill(Rp,XBorder,YBorder-6,(25*8)+XBorder,YBorder+(100)-4);
  239.    SetAPen(Rp,1);
  240. }
  241.  
  242. Parentize(str) /*Convert a directory identifier string into the one*/
  243. char *str;        /*for its parent directory*/
  244. {
  245.    int c;
  246.  
  247.    if(str[strlen(str)-1]==':')   /*If ':' is the last character*/
  248.       return(FALSE);          /*We're at the root, and cannot back up*/
  249.    for(c=strlen(str)-1;c >= 0;c--)
  250.       if(str[c]=='/')   /*Delete last '/' & everything after that*/
  251.          {
  252.          str[c]=NULL;
  253.          c=0;
  254.          }
  255.       else
  256.          if(str[c]==':')   /*Or delete everything after the ':'*/
  257.             {              /*(which leaves the root)*/
  258.             str[c+1]=NULL;
  259.             c=0;
  260.             }
  261.    return(TRUE);
  262. }
  263.  
  264. UpdateSlider(Amt,Info,Gadgt) /*Update the slider bar to reflect*/
  265. USHORT Amt;             /*the number of file/dir names available for selection*/
  266. struct PropInfo *Info;
  267. struct Gadget *Gadgt;
  268. {
  269.    Info->VertBody=((0xFFFF*10)/Amt);
  270.    RefreshGadgets(Gadgt,FNWindow,NULL);
  271. }
  272.  
  273. CheckIntuiMessages(Max,header) /*Check and respond to the window's IDCMP*/
  274. USHORT Max;             /*messages*/
  275. struct fibHeader *header;
  276. {
  277.    struct fibNode *cur;
  278.    UBYTE c,line;
  279.    struct IntuiMessage *mesg;
  280.    struct Gadget *InUse;
  281.    ULONG Class;
  282.    USHORT Code;
  283.    SHORT X,Y;
  284.  
  285.    /*Assumes that the calling function has either Wait()ed or wants to*/
  286.    /*handle any IDCMP messages that have piled up*/
  287.    
  288.    while((mesg=(struct IntuiMessage *)GetMsg(FNWindow->UserPort))!=NULL)
  289.       {
  290.       InUse=(struct Gadget *)mesg->IAddress;
  291.       X=mesg->MouseX;
  292.       Y=mesg->MouseY;
  293.       Class=mesg->Class;
  294.       Code=mesg->Code;
  295.       ReplyMsg(mesg); /*Reply to the message*/
  296.       switch(Class)  /*Decide what happened*/
  297.          {
  298.          case MOUSEMOVE: /*If the mouse moved, then the silder is down, so*/
  299.             if(Max > 10) /*update the filenames in the box to reflect the*/
  300.                UpdateList(SliderSInfo.VertPot,Max,header); /*slider's*/
  301.             break;                                               /*position*/
  302.          case GADGETUP:
  303.             if(InUse->GadgetID <= 10)
  304.             {  /*One of the device gadgets was pushed*/
  305.                if(!ispipedevice(InUse->GadgetText->IText))
  306.                {        /*Find the volume name if it isn't the PIPE:*/
  307.                   MakeAbsName(InUse->GadgetText->IText);
  308.                   strcpy(DirNameSIBuff,absDirName);
  309.                   strcat(DirNameSIBuff,":");
  310.                }
  311.                else
  312.                   strcpy(DirNameSIBuff,InUse->GadgetText->IText);
  313.                RefreshGadget(&DirName,FNWindow,NULL);
  314.                return(GN_NEWDIR);
  315.             }
  316.             switch(InUse->GadgetID)
  317.             {
  318.                case 14: /*CANCEL was pushed*/
  319.                   return(GN_CANCEL);
  320.                case 12: 
  321.                case 13: /*OK was pushed or return was pressed in the*/
  322.                  return(GN_OK);  /*filename's box*/
  323.                case 15:
  324.                   return(GN_PARENT); /*PARENT was pushed*/
  325.                case 11:  /*Return was pushed while the extension or dirname*/
  326.                case 18:  /*box was active, so reread the old directory or read*/
  327.                   return(GN_NEWDIR);  /*a new one*/
  328.             }
  329.             return(GN_RIEN);     /*Nothing important*/
  330.             break;
  331.          case GADGETDOWN:     /*The .info gadget was pressed?*/
  332.          if(InUse->GadgetID == 18)
  333.             return(GN_NEWDIR);
  334.  
  335.             /*A file/dir name in the box was clicked on*/
  336.          if(!ispipedevice(DirNameSIBuff)) /*If the pipe:*/
  337.             {                             /*don't try & get a filename*/
  338.             line=(Y-YBorder+7)/10;    /*Get line clicked on*/
  339.             for(c=0,cur=(struct fibNode *)header->top;c!=line && cur!=NULL;c++)
  340.                cur=(struct fibNode *)cur->next; /*Find the file's Fib*/
  341.             if(cur != NULL)   /*If the file exists*/
  342.                if(cur->fib.fib_DirEntryType > 0)
  343.                   {   /*It's a directory, so read that directory*/
  344.                   if(DirNameSIBuff[strlen(DirNameSIBuff)-1] != ':')
  345.                      strcat(DirNameSIBuff,"/");
  346.                   strcat(DirNameSIBuff,cur->fib.fib_FileName);
  347.                   RefreshGadget(&DirName,FNWindow,NULL);
  348.                   return(GN_NEWDIR);
  349.                   }
  350.                else   /*otherwise, return the filename clicked upon*/
  351.                   {
  352.                   strcpy(filenameSIBuff,cur->fib.fib_FileName);
  353.                   RefreshGadget(&filename,FNWindow,NULL);
  354.                   }
  355.             }
  356.          }
  357.       }
  358.    return(GN_DONE);  /*All done...*/
  359. }
  360.  
  361. UpdateList(Pos,Num,header) /*Update filenames in the filename box*/
  362. USHORT Pos;                   /*According to the slider's position*/
  363. USHORT Num;
  364. struct fibHeader *header;
  365. {
  366.    static USHORT LastFirstItem=30000;
  367.    ULONG FirstItem;
  368.    FirstItem=(((Pos+1)*(Num-10)) >> 16);
  369.  
  370.    if( FirstItem != LastFirstItem)
  371.       RewriteList(FirstItem,header);
  372.    LastFirstItem=FirstItem;
  373. }
  374.  
  375. RewriteList(First,header)  /*Rewrite the list of filenames in the*/
  376. USHORT First;                 /*filename box...*/
  377. struct fibHeader *header;
  378. {
  379.    register struct fibNode *node;
  380.    register USHORT c,Y;
  381.  
  382.    if(First)   /*If we're not starting at the start...*/
  383.       for(c=0,node=(struct fibNode *)header->first;c < First;c++)
  384.          node=(struct fibNode *)node->next; /*Get the first filename*/
  385.    else     /*Otherwise, start at the top*/
  386.       node=(struct fibNode *)header->first;
  387.    header->top=(struct fibNode *)node;
  388.    
  389.    /*Print the filenames (up to 10)*/
  390.    for(c=0,Y=YBorder;(c < 10) && (node!=NULL);
  391.          c++,Y+=10,node=(struct fibNode *)node->next)
  392.       PrintFileName(&(node->fib),Rp,XBorder,Y);
  393. }
  394.  
  395. CheckExt(name,ext) /*Check to see if 'name' has the extension '.ext'*/
  396. char *name,*ext;
  397. {
  398.    if(strlen(name) >= strlen(ext))
  399.       if(strcmp(&name[strlen(name)-strlen(ext)],ext)==0)
  400.          return(TRUE);
  401.    return(FALSE);
  402. }
  403.  
  404. GetFib(header)
  405. struct fibHeader *header;
  406. {
  407.    header->last=(struct fibNode *)header->current;
  408.    if((header->current=(struct fibNode *) /*Allocate a FIB structure*/
  409.          AllocMem(sizeof(struct fibNode),MEMF_PUBLIC|MEMF_CLEAR))==NULL)
  410.       {
  411.       FreeFuncMemory(header->current); /*Whoops, it didn't work...*/
  412.       return(FALSE);
  413.       }
  414.    if(header->directory==NULL) /*Must want it for a directory...*/
  415.       header->directory=(struct fibNode *)header->current;
  416.    else  /*Append to the current FIB list*/
  417.       {
  418.       if(header->first==NULL)
  419.          {
  420.          header->directory->next=header->first=header->last=header->top=
  421.                (struct fibNode *)header->current;
  422.          CopyFIB(&(header->directory->fib),&(header->current->fib));
  423.          }
  424.       else
  425.          {
  426.          CopyFIB(&(header->last->fib),&(header->current->fib));
  427.          header->last->next=(struct fibNode *)header->current;
  428.          header->current->prev=(struct fibNode *)header->last;
  429.          }
  430.       }
  431.    return(TRUE);
  432. }
  433.  
  434. CopyFIB(from,to) /*Copy a fileinfoblock from 'from' to 'to'*/
  435. struct FileInfoBlock *from,*to;
  436. {
  437.    to->fib_DiskKey=from->fib_DiskKey;
  438.    to->fib_DirEntryType=from->fib_DirEntryType;
  439.    to->fib_Protection=from->fib_Protection;
  440.    to->fib_EntryType=from->fib_EntryType;
  441.    to->fib_Size=from->fib_Size;
  442.    to->fib_NumBlocks=from->fib_NumBlocks;
  443.    strcpy(to->fib_FileName,from->fib_FileName);
  444.    strcpy(to->fib_Comment,from->fib_Comment);
  445.    to->fib_Date.ds_Days=from->fib_Date.ds_Days;
  446.    to->fib_Date.ds_Minute=from->fib_Date.ds_Minute;
  447.    to->fib_Date.ds_Tick=from->fib_Date.ds_Tick;
  448.  
  449.    return(TRUE);
  450. }
  451.  
  452. PrintFileName(fib,RPrt,X,Y)  /*Print a filename in the filename box*/
  453. struct FileInfoBlock *fib;
  454. struct RPort *RPrt;
  455. USHORT X,Y;
  456. {
  457.    UWORD len;
  458.    char name[40];
  459.    
  460.    strcpy(name,fib->fib_FileName);
  461.    if(fib->fib_DirEntryType > 0) /*Set the pen color, according to whether*/
  462.    {        /*we're printing a filename or a directory name*/
  463.       SetAPen(RPrt,yafr_e_DirnamePenColor); 
  464.       strcat(name,"  (dir)"); /*Append '  (dir)' if it's a directory*/
  465.    }
  466.    else
  467.       SetAPen(RPrt,yafr_e_FilenamePenColor);
  468.    Move(RPrt,X,Y);
  469.    Text(RPrt,"                         ",25);  /*Blank out the space*/
  470.    Move(RPrt,X,Y);
  471.    len = (strlen(fib->fib_FileName)<=25) ? strlen(fib->fib_FileName) : 25;
  472.    Text(RPrt,fib->fib_FileName,len);   /*Trundicate the filename at 25 chars*/
  473.                                        /*and print it.*/
  474. }
  475.  
  476. RefreshGadget(Gadg,Wdw,Req) /*Refresh a specific gadget*/
  477. struct Gadget *Gadg;           /*(keeps RefreshGadgets() from refreshing*/
  478. struct Window *Wdw;            /*the entire gadget list*/
  479. struct Req *Req;
  480. {
  481.    struct Gadget *next;
  482.    next=(struct Gadget *)Gadg->NextGadget;
  483.    Gadg->NextGadget=NULL;
  484.    RefreshGadgets(Gadg,Wdw,Req);
  485.    Gadg->NextGadget=(struct Gadget *)next;
  486.    return(TRUE);
  487. }
  488.  
  489. FreeFuncMemory(first)   /*Free the memory taken up by a fib list*/
  490. register struct fibNode *first;
  491. {
  492.    register struct fibNode *next,*current;
  493.    next=(struct fibNode *)first->next;
  494.    FreeMem(first,sizeof(struct fibNode));
  495.    while((current=(struct fibNode *)next)!=NULL)
  496.       {
  497.       next=(struct fibNode *)current->next;
  498.       FreeMem(current,sizeof(struct fibNode));
  499.       }
  500. }
  501.  
  502. ispipedevice(device) /*Checks to see if the device is the PIPE:*/
  503. char *device;
  504. {
  505.    char temp[6];
  506.    int c;
  507.    for(c=0;c<5;c++) /*Convert weird capitalization (pIPe:) to pipe:*/
  508.       temp[c]=tolower(device[c]); /*So as to make it easy to check*/
  509.    temp[5]=NULL;
  510.    if(strcmp(device,"pipe:")==0)
  511.       return(TRUE);
  512.    else
  513.       return(FALSE);  
  514. }
  515.  
  516. /*!*******************************************************************
  517.  * FindRoot by Bruce Rogers 1/20/90
  518.  *********************************************************************/
  519.  
  520. /*!*******************************************************************
  521.  * Kludges disk:name/directory with filename so we can just read it.
  522.  *********************************************************************/
  523. void    DosConcatenate(string1,string2,result)
  524. char    string1[],string2[],result[];
  525. {
  526. short   i,j;
  527.  
  528.     for(i=0; string1[i] != '\0'; i++)
  529.         result[i]=string1[i];
  530.     if ((result[i-1] != ':') && (result[i-1] != '/') && (i!=0) && string2[0]!=0)
  531.     {
  532.         result[i]='/';
  533.         ++i;
  534.     }
  535.     for(j=0; string2[j] != '\0'; j++)
  536.         result[i+j] = string2[j];
  537.     result[i+j] = '\0';
  538. }
  539.  
  540. /*!*******************************************************************
  541.  * Recursively go up parent chain, looking for oldest parent.
  542.  * Create the absolute path string as we go.
  543.  *********************************************************************/
  544. SeekRoot(oldlock)
  545. ULONG   oldlock;
  546. {
  547. short   i;
  548. struct  FileInfoBlock   fileInfo;
  549. ULONG   newlock;
  550.  
  551.     Examine(oldlock,&fileInfo);
  552.     DosConcatenate(fileInfo.fib_FileName,absDirName,absDir);
  553.     for(i=0;i<MAXPATHSTRING;i++) absDirName[i]=absDir[i];
  554.     newlock=ParentDir(oldlock);
  555.     UnLock(oldlock);
  556.     oldlock=newlock;
  557.     if (oldlock!=NULL) SeekRoot(oldlock);
  558. }
  559.  
  560. /*!*******************************************************************
  561.  * Given a path, sets absDirName equal to the absolute path
  562.  *********************************************************************/
  563.         MakeAbsName(dirName)
  564. char    *dirName;
  565. {
  566. short   i;
  567. ULONG   lock;
  568.  
  569.     for(i=0;i<MAXPATHSTRING;i++) absDirName[i]=absDir[i]=0;
  570.     lock=Lock(dirName,ACCESS_READ);
  571.     if (lock==NULL) return;
  572.     SeekRoot(lock);
  573.     for(i=0;i<MAXPATHSTRING;i++)
  574.     {
  575.         if (absDirName[i]=='/')
  576.         {
  577.             absDirName[i]=':';
  578.             break;
  579.         }
  580.     }
  581. }
  582.  
  583. /*End of YAFR.c*/
  584.